bsearch関数は、配列中から該当する要素を検索します。配列の内容は昇順にソートされていなければなりません。
#include <stdlib.h>
void bsearch(const void *key, void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
*keyは検索キーを指定します。
*baseは検索対象の配列を指定します。
nmembは配列の要素数を指定します。
sizeは配列要素の大きさをバイト単位で指定します。
*comparは検索キーの大小関係をbsearch関数に知らせる関数を指定します。
戻り値として、検索が成功した場合は、当該要素へのポインタが、失敗した場合は、NULLが返ります。該当する要素が複数あった場合は、どの要素が返されるかは不定です。
第5引数に指定する関数はbsearch関数から呼び出され、仮引数として比較対象の2つの要素が渡ってきます。要素中の検索キーの大小関係をチェックして戻り値として、次の値を返します。(第1引数は*keyです。)
- 第1引数が第2引数に対して小さい場合は、0より小さい値を返します。
- 第1引数と第2引数が等しい場合は、0を返します。
- 第1引数が第2引数に対して大きい場合は、0より大きい値を返します。
次の例題プログラムは、ファイルの内容を構造体配列に読み込んで、番号を検索キーにして検索しています。なお、ファイルの内容は番号をキーとして、昇順にソートしてあります。
プログラム 例
#include <stdio.h> #include <stdlib.h> /* メンバーの個人情報 */ struct member { int number; /* 番号 */ char name[20]; /* 名前 */ double height; /* 身長 */ double weight; /* 体重 */ double jump; /* 最高到達点 */ }; /* bsearch関数の検索キー比較関数 */ int SearchComp(const void *, const void *); int main() { FILE *fp; struct member member_list[20]; struct member key; /* 検索キー */ struct member *res; /* 検索結果 */ int list_cnt; if ((fp = fopen('beijing_2008.csv', 'r')) == NULL) { fprintf(stderr, 'ファイルのオープンに失敗しました\n'); abort(); } list_cnt = 0; /* メンバー情報入力 */ while(fscanf(fp, '%d,%[A-Za-z],%lf,%lf,%lf', &member_list[list_cnt].number, member_list[list_cnt].name, &member_list[list_cnt].height, &member_list[list_cnt].weight, &member_list[list_cnt].jump) != EOF) { ++list_cnt; } fclose(fp); while (1) { printf('検索する選手の番号を入力してください ==> '); scanf('%d', &key.number); if (key.number != 0) { /* member_listを番号をキーにして検索 */ res = bsearch(&key, member_list, list_cnt, sizeof(struct member), SearchComp); if (res != NULL) { printf('番号 名前 身長 体重 最高到達点\n'); /* 検索結果を出力 */ printf('%3d %-20s %6.1f %6.1f %6.1f\n', res->number, res->name, res->height, res->weight, res->jump); } else { printf('検索できませんでした\n'); } } else { break; } } return 0; } /* bsearch関数の検索キー比較関数 */ int SearchComp(const void *p1, const void *p2) { struct member *cmp1 = (struct member *)p1; struct member *cmp2 = (struct member *)p2; return (cmp1->number - cmp2->number); }
例の実行結果
$ cat beijing_2008.csv 1,kurihara,186,69,305 2,tajimi,180,70,309 3,takesita,159,52,280 4,oomura,184,70,319 5,takahasi,170,65,290 6,sano,159,54,260 7,sugiyama,184,66,310 8,sakurai,167,63,290 9,kanou,174,65,298 11,araki,186,79,307 12,kimura,184,66,298 14,kawai,168,63,280 $ $ ./bsearch.exe 検索する選手の番号を入力してください ==> 1 番号 名前 身長 体重 最高到達点 1 kurihara 186.0 69.0 305.0 検索する選手の番号を入力してください ==> 14 番号 名前 身長 体重 最高到達点 14 kawai 168.0 63.0 280.0 検索する選手の番号を入力してください ==> 10 検索できませんでした 検索する選手の番号を入力してください ==> 7 番号 名前 身長 体重 最高到達点 7 sugiyama 184.0 66.0 310.0 検索する選手の番号を入力してください ==> 15 検索できませんでした 検索する選手の番号を入力してください ==> 0 $